package com.itlong.cloud.property.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.app.AppImageDTO;
import com.itlong.cloud.POJO.DTO.property.DeviceAiCameraInfoDTO;
import com.itlong.cloud.POJO.PO.DeviceAICameraInfoPO;
import com.itlong.cloud.POJO.PO.DeviceBusinessElevatorChangeLogPO;
import com.itlong.cloud.POJO.VO.property.PropertyDeviceAiCameraInfoVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.CloudElevatorChangeBusinessEnum;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.property.dao.IPropertyAICameraDao;
import com.itlong.cloud.property.service.IPropertyAICameraService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.string.StringUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <desc>
 *      ai摄像头管理服务层接口实现类
 * </desc>
 *
 * @createDate2021/5/28
 **/
@Service
@RefreshScope
public class PropertyAICameraServiceImpl implements IPropertyAICameraService {

    @Autowired
    IPropertyAICameraDao iPropertyAICameraDao;

    @Autowired
    RedisService redisService;

    @Autowired
    private MessageSender messageSender;


    /**
     * <desc>
     *      添加AI摄像头
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String save(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception {

        //组装AI摄像头相关数据进行持久化
        String projectId = StringHandlerUtil.getProjectIdByDeviceUnique(cameraInfoDTO.getElevatorDeviceUnique());
        DeviceAICameraInfoPO cameraInfoPO = new DeviceAICameraInfoPO(LogicIdUtil.bussinessId(),cameraInfoDTO.getElevatorDeviceUnique(),
                projectId,cameraInfoDTO.getDeviceName(),cameraInfoDTO.getDeviceIp(),
                cameraInfoDTO.getRemark(),cameraInfoDTO.getDeviceModel());
        cameraInfoPO.setCreateTime(new Date());
        cameraInfoPO.setUpdateTime(new Date());
        cameraInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        iPropertyAICameraDao.save(SqlUtil.durableData(cameraInfoPO, PlatformConstants.TABLE_SAVE));

        //组装指令将电梯所绑定的AI摄像头相关信息下发给设备
        this.pushData(cameraInfoDTO);

        return cameraInfoPO.getCameraId();
    }

    /**
     * <desc>
     *      修改AI摄像头
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public String update(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception {

        //查出修改前的数据
        PropertyDeviceAiCameraInfoVO aiCameraDetails = iPropertyAICameraDao.getAiCameraDetails(cameraInfoDTO);
        DeviceAICameraInfoPO cameraInfoPO = new DeviceAICameraInfoPO(cameraInfoDTO.getDeviceId(),cameraInfoDTO.getElevatorDeviceUnique(),
                StringHandlerUtil.getProjectIdByDeviceUnique(cameraInfoDTO.getElevatorDeviceUnique()),cameraInfoDTO.getDeviceName(),cameraInfoDTO.getDeviceIp(),
                cameraInfoDTO.getRemark(),cameraInfoDTO.getDeviceModel());
        cameraInfoPO.setUpdateTime(new Date());
        cameraInfoPO.setAlarmStatus(cameraInfoDTO.getAlarmStatus());
        cameraInfoPO.setUploadStatus(cameraInfoDTO.getUploadStatus());
        iPropertyAICameraDao.update(SqlUtil.durableData(cameraInfoPO, PlatformConstants.TABLE_UPDATE));

        //比对电梯所配置的摄像头参数是否发生了变更，若变更则需向电梯推送指令
        if(cameraInfoDTO.getElevatorDeviceUnique().equals(aiCameraDetails.getElevatorDeviceUnique())&&(!cameraInfoDTO.getDeviceIp().equals(aiCameraDetails.getDeviceIp())||
                (cameraInfoDTO.getAlarmStatus()!=null && cameraInfoDTO.getUploadStatus()!=null) &&
                        (cameraInfoDTO.getAlarmStatus()!=aiCameraDetails.getAlarmStatus() || cameraInfoDTO.getUploadStatus()!= aiCameraDetails.getUploadStatus()))){
            //组装指令将电梯所绑定的AI摄像头相关信息下发给设备
            this.pushData(cameraInfoDTO);
        }else if(!cameraInfoDTO.getElevatorDeviceUnique().equals(aiCameraDetails.getElevatorDeviceUnique())){
            //如果所绑摄像头电梯发生变化，则需推送两条指令（所绑定的新旧设备）
            this.pushData(cameraInfoDTO);
            cameraInfoDTO.setElevatorDeviceUnique(aiCameraDetails.getElevatorDeviceUnique());
            this.pushData(cameraInfoDTO);
        }

        return cameraInfoPO.getCameraId();
    }

    /**
     * <desc>
     *      校验电梯是否已绑定其它摄像头
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return 结果集数量
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    public Integer checkElevatorIsBind(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception{
        return iPropertyAICameraDao.checkElevatorIsBind(cameraInfoDTO);
    }

    /**
     * <desc>
     *      根据设备ID获取AI摄像头详情
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    public PropertyDeviceAiCameraInfoVO getAiCameraDetails(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception{
        return iPropertyAICameraDao.getAiCameraDetails(cameraInfoDTO);
    }

    /**
     * <desc>
     *      批量删除ai摄像头信息
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void batchRemove(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception{
        String[] deviceIds = StringHandlerUtil.splitString(cameraInfoDTO.getDeviceIds());
        //查询待删除的ai摄像头相关信息
        List<PropertyDeviceAiCameraInfoVO> list = iPropertyAICameraDao.getAiCameraDetailsByDeviceIds(deviceIds);
        //批量删除
        iPropertyAICameraDao.batchRemove(deviceIds);
        for(PropertyDeviceAiCameraInfoVO cameraInfoVO : list){
            cameraInfoDTO.setElevatorDeviceUnique(cameraInfoVO.getElevatorDeviceUnique());
            //组装指令将电梯所绑定的AI摄像头相关信息下发给设备
            this.pushData(cameraInfoDTO);
        }
    }

    /**
     * <desc>
     *      AI摄像头列表
     * </desc>
     *
     * @param cameraInfoDTO 摄像头相关请求入参DTO
     * @return 列表数据
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    @Override
    public Page<PropertyDeviceAiCameraInfoVO> getAiCameraListByPage(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception{

        //查询缓存中所有定义摄像头为前缀的Key,交且过滤出在线设备Id集合
        Set<String> resultCamera = redisService.getKeys(RedisConstant.DEVICE_AI_CAMERA_IS_ONLINE_KEY) == null ? new HashSet<>() : redisService.getKeys(RedisConstant.DEVICE_AI_CAMERA_IS_ONLINE_KEY);//AI摄像头在线设备
        if (resultCamera.size() > 0){
            resultCamera = getOnlineDevice(resultCamera,cameraInfoDTO.getProjectId());
        }
        String[] strResult = new String[resultCamera.size()];
        String[] strResultCamera = resultCamera.toArray(strResult);
        for (int i = 0; i < strResultCamera.length; i++) {
            strResultCamera[i] = strResultCamera[i].replace(RedisConstant.DEVICE_AI_CAMERA_IS_ONLINE_KEY, "");
        }
        if (StringUtils.isBlank(cameraInfoDTO.getOrderColumn())) {
            cameraInfoDTO.setOrderColumn("camera.create_time");
            cameraInfoDTO.setOrderRule("DESC");
        }
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(cameraInfoDTO);
        params.put("deviceIds", strResultCamera.length == 0 ? new String[]{""} : strResultCamera);
        //分页类默认pageSize为20
        Page<PropertyDeviceAiCameraInfoVO> page = new Page<>();
        page.getPage().setPageSize(cameraInfoDTO.getPageSize());
        page.getPage().setCurrentPage(cameraInfoDTO.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        List<PropertyDeviceAiCameraInfoVO> list = iPropertyAICameraDao.getAiCameraListByPage(params);

        //查询出分布结果集，从缓存中赋值于AI摄像头在线离线状态
        for(PropertyDeviceAiCameraInfoVO aiCameraInfoVO : list) {
            String cameraOnline = redisService.get(RedisConstant.DEVICE_AI_CAMERA_IS_ONLINE_KEY + aiCameraInfoVO.getDeviceId());
            String elevatorOnline = redisService.get(RedisConstant.DEVICE_ELEVATOR_IS_ONLINE_KEY + aiCameraInfoVO.getElevatorDeviceUnique());
            aiCameraInfoVO.setIsOnline(("1".equalsIgnoreCase(cameraOnline) && "1".equals(elevatorOnline)) ? "1" : "0");
        }

        //填充返回数据集
        page.setRows(list, iPropertyAICameraDao.getAiCameraListByPageCount(params));
        return page;
    }

    /**
     * <desc>
     * 获取在线设备 过滤不在线设备
     * <desc/>
     *
     * @param resultCamera 设备在线信息
     * @return
     * @author Juguang.S
     * @createDate 2021/06/02
     */
    private Set<String> getOnlineDevice (Set<String> resultCamera,String projectId){
        Set<String>  cameraSet = new HashSet<>();
        Map<String,String> map = new HashMap<>();
        Set<String> elevatorSet = new HashSet<>();
        List<PropertyDeviceAiCameraInfoVO> list = iPropertyAICameraDao.getAiCameraList(projectId);
        for(PropertyDeviceAiCameraInfoVO cameraInfoVO : list){
            if("1".equals(redisService.get(RedisConstant.DEVICE_ELEVATOR_IS_ONLINE_KEY + cameraInfoVO.getElevatorDeviceUnique()))){
                elevatorSet.add(cameraInfoVO.getDeviceId());
            }
        }

        for ( String key : resultCamera){
            String aiCameraId = key.replace(RedisConstant.DEVICE_AI_CAMERA_IS_ONLINE_KEY, "");
            if ("1".equals(redisService.get(key)) && elevatorSet.contains(aiCameraId)){
                cameraSet.add(key);
            }
        }
        return cameraSet;
    }

    /**
     * <desc>
     *      向云电梯推送指令
     * <desc/>
     *
     * @param cameraInfoDTO 摄像头相关信息
     * @return
     * @author Juguang.S
     * @createDate 2021/06/03
     */
    private void pushData(DeviceAiCameraInfoDTO cameraInfoDTO) throws Exception{

        //组装指令将电梯所绑定的AI摄像头相关信息下发给设备
        String projectId = StringHandlerUtil.getProjectIdByDeviceUnique(cameraInfoDTO.getElevatorDeviceUnique());
        JSONObject elevatorObject = new JSONObject();
        elevatorObject.put("projectId",projectId);
        elevatorObject.put("deviceUnique",cameraInfoDTO.getElevatorDeviceUnique());
        List<DeviceBusinessElevatorChangeLogPO> changeLogPOs = new ArrayList<>();
        changeLogPOs.add(new DeviceBusinessElevatorChangeLogPO(projectId, CloudElevatorChangeBusinessEnum.PUSH_PROJECT,elevatorObject.toJSONString()));
        JSONObject elevatorJs = new JSONObject();
        elevatorJs.put("data",changeLogPOs);
        messageSender.send(
                RabbitMQConstant.RABBITMQ_HANDLE_CLOUD_ELEVATOR_CHANGE_BUSINESS_QUEUE,
                JsonUtil.toJSON(elevatorJs),
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_EXCHANGE,
                RabbitMQConstant.RABBITMQ_CLOUD_ELEVATOR_CHANGE_BUSINESS_ROUTING_KEY);
    }


}
